/**
 * 
 */
package br.edu.catolica.sadbc.manager;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.persistence.Query;

import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.framework.EntityQuery;

import br.edu.catolica.sadbc.core.exception.BusinessObjectException;
import br.edu.catolica.sadbc.core.exception.ValidateBusinessRulesException;
import br.edu.catolica.sadbc.core.manager.AbstractCrudManager;
import br.edu.catolica.sadbc.core.util.StringUtil;
import br.edu.catolica.sadbc.entity.Usuario;
import br.edu.catolica.sadbc.entity.enums.SituacaoUsuario;
import br.edu.catolica.sadbc.entity.enums.TipoUsuario;
import br.edu.catolica.sadbc.entity.filter.UsuarioSearchFilter;

/**
 * @author robert.resende
 *
 */
@AutoCreate
@Name(value = "usuarioManager")
public class UsuarioManager extends AbstractCrudManager<Usuario> {
	
	private static final String ejbql = "select obj from Usuario obj";
	private static final String operator_and = "and";
	private static final String operator_or = "or";
	private String[] restriction = {
			" obj.tipoUsuario = #{usuarioSearchFilter.tipoUsuario} ",
			" obj.status = #{usuarioSearchFilter.status} ",
			" lower(obj.nomeUsuario) like concat(lower(#{usuarioSearchFilter.nomeUsuario}), '%') ",
			" lower(obj.nomeAvaliador) like concat(lower(#{usuarioSearchFilter.nomeAvaliador}), '%') "};

	public Usuario buscarUsuarioById(Long id) {
		return this.entityManager.find(Usuario.class, id);
	}
	
	@Override
	public String update(Usuario usuario) throws ValidateBusinessRulesException, BusinessObjectException {
		Usuario user = this.entityManager.find(Usuario.class, usuario.getId());
		String senha = encrypt(usuario.getSenhaAtual(), usuario.getNomeUsuario());
		
		if (!user.getSenha().equals(senha)) {
			throw new ValidateBusinessRulesException("Senha atual não confere.");
		}
		
		if (!usuario.getSenhaNova().equals(usuario.getConfirmaSenha())) {
			throw new ValidateBusinessRulesException("Novas senhas digitadas não conferem.");
		}
		
		senha = encrypt(usuario.getSenhaNova(), usuario.getNomeUsuario());
		usuario.setSenha(senha);
		return super.update(usuario);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<Usuario> pesquisarAvaliador(UsuarioSearchFilter usuarioSearchFilter) {
		List<Usuario> lista = new ArrayList<Usuario>();
		EntityQuery entityQuery = new EntityQuery();
		entityQuery.setEjbql(ejbql);
		entityQuery.setRestrictionExpressionStrings(Arrays.asList(restriction));
		if (usuarioSearchFilter != null && usuarioSearchFilter.getStatus() != null) {
			entityQuery.setRestrictionLogicOperator(operator_and);
		} else {
			entityQuery.setRestrictionLogicOperator(operator_or);
		}
		lista = entityQuery.getResultList();
		log.info("Lista vazia: " + lista.isEmpty());
		log.info("Tamanho da lista: " + lista.size());
		return lista;
	}
	
	public String salvarAvaliador(Usuario usuario) throws ValidateBusinessRulesException, BusinessObjectException {
		doValidateBussinessRulesAvaliador(usuario);
		doPreInsertAvaliador(usuario);
		return super.salvar(usuario);
	}
	
	public String atualizarAvaliador(Usuario usuario) throws ValidateBusinessRulesException, BusinessObjectException {
		
		if (!usuario.getSenha().equalsIgnoreCase(usuario.getConfirmaSenha())) {
			throw new ValidateBusinessRulesException("Senhas digitadas não conferem.");
		}
		
		doPreUpdateAvaliador(usuario);
		return super.update(usuario);
	}

	public String excluirAvaliador(Usuario usuario) throws BusinessObjectException {
		doPreExcludeAvaliador(usuario);
		return super.update(usuario);
	}

	public String incluirAvaliador(Usuario usuario) throws BusinessObjectException {
		doPreIncludeAvaliador(usuario);
		return super.update(usuario);
	}
	
	private void doPreUpdateAvaliador(Usuario usuario) {
		usuario.setSenha(encrypt(usuario.getSenha(), usuario.getNomeUsuario()));
	}
	
	private void doPreExcludeAvaliador(Usuario usuario) {
		usuario.setStatus(SituacaoUsuario.INATIVO.getValue());
	}

	private void doPreIncludeAvaliador(Usuario usuario) {
		usuario.setStatus(SituacaoUsuario.ATIVO.getValue());
	}
	
	private void doPreInsertAvaliador(Usuario usuario) {
		usuario.setTipoUsuario(TipoUsuario.AVALIADOR.getValue());
		usuario.setStatus(SituacaoUsuario.ATIVO.getValue());
		usuario.setSenha(encrypt(usuario.getSenha(), usuario.getNomeUsuario()));
	}
	
	@SuppressWarnings({ "unchecked" })
	private void doValidateBussinessRulesAvaliador(Usuario usuario) throws ValidateBusinessRulesException {
		if (!usuario.getSenha().equalsIgnoreCase(usuario.getConfirmaSenha())) {
			throw new ValidateBusinessRulesException("Senhas digitadas não conferem.");
		}
		
		if (StringUtil.getInstance().isMenor(5, usuario.getNomeAvaliador())) {
			throw new ValidateBusinessRulesException("Nome do avaliador menos que 5 caracteres.");
		}
		
		List<Usuario> usuarioResponse = new ArrayList<Usuario>();
		Query q = this.entityManager.createQuery("select u from Usuario u where upper(u.nomeUsuario) = upper(:nomeusuario)");
		q.setParameter("nomeusuario", usuario.getNomeUsuario());
		usuarioResponse = (List<Usuario>) q.getResultList();
		
		if (usuarioResponse != null && !usuarioResponse.isEmpty()) {
			throw new ValidateBusinessRulesException("Nome de usuário já existente.");
		}
	}

}
